<?php

/*
 * This file is part of the php-phantomjs.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Ling\PhantomJs\Http;

use Ling\PhantomJs\Procedure\OutputInterface;
use Ling\PhantomJs\Http\ResponseInterface;

/**
 * PHP PhantomJs
 *
 * @author Jon Wenmoth <contact@Ling.me>
 */
class Response
    implements ResponseInterface, OutputInterface
{
    /**
     * Http headers array
     *
     * @var array
     * @access public
     */
    public array $headers;

    /**
     * Response int
     *
     * @var int
     * @access public
     */
    public int $status;

    /**
     * Response body
     *
     * @var string
     * @access public
     */
    public string $content = '';

    /**
     * Response content type header
     *
     * @var string
     * @access public
     */
    public string $contentType;

    /**
     * Requested URL
     *
     * @var string
     * @access public
     */
    public string $url;

    /**
     * Redirected URL
     *
     * @var string|null
     * @access public
     */
    public ?string $redirectURL;

    /**
     * Request time string
     *
     * @var string
     * @access public
     */
    public string $time;

    /**
     * Console messages
     *
     * @var array
     * @access public
     */
    public array $console;

    /**
     * Session cookies
     *
     * @var array
     * @access public
     */
    public array $cookies;

    /**
     * Import response data
     *
     * @access public
     * @param array $data
     * @return Response
     */
    public function import(array $data): Response
    {
        foreach ($data as $param => $value) {

            if ($param === 'headers') {
                continue;
            }

            if (property_exists($this, $param)) {
                $this->$param = $value;
            }
        }

        $this->headers = [];

        if (isset($data['headers'])) {
            $this->setHeaders((array)$data['headers']);
        }

        return $this;
    }

    /**
     * Set headers array
     *
     * @access protected
     * @param array $headers
     * @return Response
     */
    protected function setHeaders(array $headers): Response
    {
        foreach ($headers as $header) {

            if (isset($header['name']) && isset($header['value'])) {
                $this->headers[$header['name']] = $header['value'];
            }
        }

        return $this;
    }

    /**
     * Get HTTP headers array
     *
     * @access public
     * @return array
     */
    public function getHeaders(): array
    {
        return $this->headers;
    }

    /**
     * Get HTTP header value for code
     *
     * @access public
     * @param string $code
     * @return mixed
     */
    public function getHeader(string $code): mixed
    {
        if (isset($this->headers[$code])) {
            return $this->headers[$code];
        }

        return null;
    }

    /**
     * Get response status code
     *
     * @access public
     * @return integer
     */
    public function getStatus(): int
    {
        return $this->status;
    }

    /**
     * Get page content from response
     *
     * @access public
     * @return string
     */
    public function getContent(): string
    {
        return $this->content;
    }

    /**
     * Get content type header
     *
     * @access public
     * @return string
     */
    public function getContentType(): string
    {
        return $this->contentType;
    }

    /**
     * Get request URL
     *
     * @access public
     * @return string
     */
    public function getUrl(): string
    {
        return $this->url;
    }

    /**
     * Get redirect URL (if redirected)
     *
     * @access public
     * @return string
     */
    public function getRedirectUrl(): string
    {
        return $this->redirectURL;
    }

    /**
     * Is response a redirect
     *  - Checks status codes
     *
     * @access public
     * @return boolean
     */
    public function isRedirect(): bool
    {
        $status = $this->getStatus();

        return $status >= 300 && $status <= 307;
    }

    /**
     * Get time string
     *
     * @access public
     * @return string
     */
    public function getTime(): string
    {
        return $this->time;
    }

    /**
     * Get console messages
     *
     * @access public
     * @return array
     */
    public function getConsole(): array
    {
        return $this->console;
    }

    /**
     * Get session cookies
     *
     * @access public
     * @return array
     */
    public function getCookies(): array
    {
        return $this->cookies;
    }
}
